﻿using UnityEngine;
using Mapbox.Directions;
using System.Collections.Generic;
using System.Linq;
using Mapbox.Unity.Map;
using Mapbox.Unity.MeshGeneration.Data;
using Mapbox.Unity.MeshGeneration.Modifiers;
using Mapbox.Utils;
using Mapbox.Unity.Utilities;


public class CustomDirectionsFactory : MonoBehaviour {

    [SerializeField]
    AbstractMap _map;

    [SerializeField]
    MeshModifier[] MeshModifiers;

    [SerializeField]
    Transform[] _waypoints;

    [SerializeField]
    Material _material;

    [SerializeField]
    float _directionsLineWidth;

    private Directions _directions;
    private int _counter;

    GameObject _directionsGO;

    public List<Vector3> guideTargetPoint;

    void Awake()
    {
        if (_map == null)
        {
            _map = FindObjectOfType<AbstractMap>();
        }
        _directions = Mapbox.Unity.MapboxAccess.Instance.Directions;
    }

    public void SpawnGuidePath()
    {
        Query();
    }

    public void DestroyPath()
    {
        Destroy(_directionsGO);
    }

    void Query()
    {
        var count = _waypoints.Length;
        var wp = new Vector2d[count];
        for (int i = 0; i < count; i++)
        {
            wp[i] = _waypoints[i].GetGeoPosition(_map.CenterMercator, _map.WorldRelativeScale);
        }
        var _directionResource = new DirectionResource(wp, RoutingProfile.Driving);
        _directionResource.Steps = true;
        _directions.Query(_directionResource, HandleDirectionsResponse);
    }

    //根据返回的json信息，处理mesh顶点数据
    void HandleDirectionsResponse(DirectionsResponse response)
    {
        if (null == response.Routes || response.Routes.Count < 1)
        {
            return;
        }

        guideTargetPoint = new List<Vector3>();
        var meshData = new MeshData();
        var dat = new List<Vector3>();
        foreach (var point in response.Routes[0].Geometry)
        {
            guideTargetPoint.Add(_map.GeoToWorldPosition(new Vector2d(point.x, point.y)));
            dat.Add(Conversions.GeoToWorldPosition(point.x, point.y, _map.CenterMercator, _map.WorldRelativeScale).ToVector3xz());
        }

        var feat = new VectorFeatureUnity();
        feat.Points.Add(dat);

        foreach (MeshModifier mod in MeshModifiers.Where(x => x.Active))
        {
            var lineMod = mod as LineMeshModifier;
            if (lineMod != null)
            {
                lineMod.Width = _directionsLineWidth / _map.WorldRelativeScale;
            }
            mod.Run(feat, meshData, _map.WorldRelativeScale);
        }

        CreateGameObject(meshData);
    }

    //根据顶点数据生成mesh
    GameObject CreateGameObject(MeshData data)
    {
        if (_directionsGO != null)
        {
            Destroy(_directionsGO);
        }
        _directionsGO = new GameObject("direction waypoint " + " entity");
        var mesh = _directionsGO.AddComponent<MeshFilter>().mesh;
        mesh.subMeshCount = data.Triangles.Count;

        mesh.SetVertices(data.Vertices);
        _counter = data.Triangles.Count;
        for (int i = 0; i < _counter; i++)
        {
            var triangle = data.Triangles[i];
            mesh.SetTriangles(triangle, i);
        }

        _counter = data.UV.Count;
        for (int i = 0; i < _counter; i++)
        {
            var uv = data.UV[i];
            mesh.SetUVs(i, uv);
        }

        mesh.RecalculateNormals();
        _directionsGO.AddComponent<MeshRenderer>().material = _material;
        return _directionsGO;
    }
}
